package com.ruoyi.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.ClientUtils;
import com.ruoyi.common.OrderNumUtil;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MqttLockUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.app.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.mapper.app.*;
import com.ruoyi.system.service.DeviceService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    PowerBillingMapper powerBillingMapper;
    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    DeviceSpaceMapper deviceSpaceMapper;
    @Autowired
    MqttLockUtil mqttLockUtil;
    @Autowired
    DeviceWarningMapper deviceWarningMapper;
    @Autowired
    RechargeOrderMapper rechargeOrderMapper;
    @Autowired
    CommunityMapper communityMapper;
    @Autowired
    DeptWxInfoMapper deptWxInfoMapper;
    @Autowired
    SysDeptMapper sysDeptMapper;
    @Autowired
    SysDeptMapper deptMapper;
    @Autowired
    SysUserMapper sysUserMapper;

    @Autowired
    CommunityMemberMapper communityMemberMapper;

    @Override
    public DeptWxInfo getDeptWxInfo(Long deptId) {
        SysDept sysDept = sysDeptMapper.selectDeptById(deptId);
        if (StringUtils.isNull(sysDept)) {
            throw new ServiceException("区域不存在");
        }
        if (sysDept.getParentId() != 100) {
            throw new ServiceException("区域不符合条件！");
        }
        DeptWxInfo deptWxInfo = deptWxInfoMapper.selectByPrimaryKey(deptId);
        if (StringUtils.isNull(deptWxInfo)) {
            deptWxInfo = new DeptWxInfo();
            deptWxInfo.setDeptId(deptId);
            deptWxInfoMapper.insertSelective(deptWxInfo);
        }
        return deptWxInfo;
    }

    @Override
    public void setDeptWxInfo(Long deptId, String appId, String appSecret, String mchId, String wxKey) {
        SysDept sysDept = sysDeptMapper.selectDeptById(deptId);
        if (StringUtils.isNull(sysDept)) {
            throw new ServiceException("区域不存在");
        }
        if (sysDept.getParentId() != 100) {
            throw new ServiceException("区域不符合条件！");
        }
        DeptWxInfo deptWxInfo = deptWxInfoMapper.selectByPrimaryKey(deptId);
        if (StringUtils.isNull(deptWxInfo)) {
            deptWxInfo = new DeptWxInfo();
            deptWxInfo.setDeptId(deptId);
            deptWxInfo.setAppId(appId);
            deptWxInfo.setAppSecret(appSecret);
            deptWxInfo.setMchId(mchId);
            deptWxInfo.setWxKey(wxKey);
            deptWxInfoMapper.insertSelective(deptWxInfo);
        }else {
            deptWxInfo.setDeptId(deptId);
            deptWxInfo.setAppId(appId);
            deptWxInfo.setAppSecret(appSecret);
            deptWxInfo.setMchId(mchId);
            deptWxInfo.setWxKey(wxKey);
            deptWxInfoMapper.updateByPrimaryKeySelective(deptWxInfo);
        }
    }

    @Override
    public void deviceBindCommunity(Long communityId, String deviceNum) {
        Device device = deviceMapper.selectByNum(deviceNum);
        if (StringUtils.isNull(device)) {
            throw new ServiceException("设备不存在！");
        }
        if (StringUtils.isNotNull(device.getCommunityId())) {
            throw new ServiceException("设备已绑定小区！");
        }

        Community community = communityMapper.selectByPrimaryKey(communityId);
        if (StringUtils.isNull(community)) {
            throw new ServiceException("小区不存在！");
        }
        if (StringUtils.isNull(community.getOperatorId())) {
            throw new ServiceException("小区未绑定运营商！");
        }
        device.setCommunityId(communityId);
        device.setCommunityName(community.getCommunityName());
        device.setOperatorId(community.getOperatorId());
        device.setOperatorName(community.getOperatorName());
        deviceMapper.updateByPrimaryKeySelective(device);
    }

    @Override
    public void deviceUnBindCommunity(Long deviceId) {
        deviceMapper.unBindCommunity(deviceId);
    }

    @Override
    public List<PowerBilling> getPowerBilling(Long deviceId) {
        return powerBillingMapper.getPowerBilling(deviceId);
    }

    @Override
    public void resetPowerBilling(List<PowerBilling> powerBillings) {
        powerBillingMapper.delByDeviceId(powerBillings.get(0).getDeviceId());
        powerBillingMapper.insertBatch(powerBillings);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addDevice(Device device) {

        if (device.getOperatorId()!= null) {
            device.setAppId(getAppId(device.getOperatorId()));
        }

        device.setCreateTime(new Date());
        deviceMapper.insertSelective(device);
        for (int i = 0;i < 2; i++) {
            DeviceSpace deviceSpace = new DeviceSpace();
            deviceSpace.setDeviceId(device.getId());
            deviceSpace.setSpaceNum(String.valueOf(i+1));
            deviceSpaceMapper.insertSelective(deviceSpace);
        }
    }

    private String getAppId(Long operatorId){
        SysDept sysDept = sysDeptMapper.selectDeptById(sysUserMapper.selectUserById(operatorId).getDeptId());
        String[] longs = sysDept.getAncestors().split(",");
        if (longs.length > 2) {
            return deptWxInfoMapper.selectByPrimaryKey(Long.valueOf(longs[2])).getAppId();
        }
        return deptWxInfoMapper.selectByPrimaryKey(sysDept.getDeptId()).getAppId();
    }

    @Override
    public void delDevice(Long deviceId) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        if (sysUser.isAdmin()) {
            deviceMapper.deleteByPrimaryKey(deviceId);
            deviceSpaceMapper.delByDeviceId(deviceId);
        }else {
            Device device = deviceMapper.selectByPrimaryKey(deviceId);
            if (StringUtils.isNotNull(device)) {
                if (device.getOperatorId().equals(sysUser.getUserId())) {
                    deviceMapper.deleteByPrimaryKey(deviceId);
                    deviceSpaceMapper.delByDeviceId(deviceId);
                }
            }
        }
    }

    @Override
    public void setDevice(Device device) {
        if (device.getOperatorId()!= null) {
            device.setAppId(getAppId(device.getOperatorId()));
        }else {
            device.setAppId(null);
        }
        deviceMapper.updateByPrimaryKey(device);
    }

    @Override
    public void socketBindQc(Long deviceId, String socketNo, String qcCode) {
        DeviceSpace check = deviceSpaceMapper.getByBindNo(qcCode);
        if (check != null) {
            Device device = deviceMapper.selectByPrimaryKey(check.getDeviceId());
            throw new ServiceException("二维码已绑定插座,插座编号:"+check.getSpaceNum()+"设备编号："+device.getDeviceNum());
        }

        DeviceSpace deviceSpace = deviceSpaceMapper.selectBySpaceId(deviceId, Integer.valueOf(socketNo));
        deviceSpace.setBindNo(qcCode);
        deviceSpaceMapper.updateByPrimaryKeySelective(deviceSpace);
    }

    @SneakyThrows
    @Override
    public AjaxResult setDeviceConfig(Device device) {
        String msgId = ClientUtils.doPostMethod("http://localhost:8610/set-config", JSONObject.toJSONString(device),"utf-8",null);

        if (device.getBillingType() == 2) {
            powerBillingMapper.delByDeviceId(device.getId());
            powerBillingMapper.insertBatch(device.getPowerBillings());
        }
        deviceMapper.updateByPrimaryKeySelective(device);
        return AjaxResult.success();

    }

    @SneakyThrows
    @Override
    public void setDeviceRestart(String deviceNum) {
        ClientUtils.doGetMethod("http://localhost:8610/restart");
    }

    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<Device> deviceList(Device device) {
        return deviceMapper.deviceList(device);
    }

    @Override
    public List<DeviceSpace> deviceSpaceList(Long deviceId) {
        List<DeviceSpace> deviceSpaces = deviceSpaceMapper.getByDeviceId(deviceId);
        for (DeviceSpace deviceSpace : deviceSpaces) {
            if (StringUtils.isNotNull(deviceSpace.getChargeStatus())&&deviceSpace.getChargeStatus() != 0) {
                deviceSpace.setRechargeOrder(rechargeOrderMapper.selectBySpace(deviceSpace.getDeviceId(),deviceSpace.getSpaceNum()));
            }
        }
        return deviceSpaces;
    }

    @SneakyThrows
    @Override
    public void deviceOpenDoor(String deviceNum, Integer holeNum, Integer type) {
        ClientUtils.doGetMethod("http://localhost:8610/open/door?deviceNum="+deviceNum+"&holeNum="+holeNum+"&type="+type);
    }
    @SneakyThrows
    @Override
    public void holeState(String deviceNum, Integer holeNum, Integer holeState) {
        ClientUtils.doGetMethod("http://localhost:8610/hole/forbidden?deviceNum="+deviceNum+"&holeNum="+holeNum+"&holeState="+holeState);
    }
    @SneakyThrows
    @Override
    public void chargeRestart(String deviceNum) {
        ClientUtils.doGetMethod("http://localhost:8610/restart?deviceNum="+deviceNum);
    }

    @Override
    public List<DeviceWarning> deviceWarningList(String deviceNum) {
        return deviceWarningMapper.deviceWarningList(deviceNum);
    }

    @Override
    public Long createRecharge(String deviceNum, Integer chargeTime, Integer socketNo) {
        Device device = deviceMapper.selectByNum(deviceNum);
        Community community = communityMapper.selectByPrimaryKey(device.getCommunityId());
        SysUser sysUser = sysUserMapper.selectUserById(device.getOperatorId());

        checkStatus(deviceNum);
        BigDecimal money = device.getTimeBilling().multiply(new BigDecimal(chargeTime));

        RechargeOrder rechargeOrder = new RechargeOrder();
        rechargeOrder.setPayType(4);
        rechargeOrder.setPreinstallTime(Long.valueOf(chargeTime));
        rechargeOrder.setUserId(SecurityUtils.getUserId());
        rechargeOrder.setUserName(SecurityUtils.getUsername());
        rechargeOrder.setUserPhone(sysUser.getPhonenumber());
        rechargeOrder.setOperatorId(sysUser.getUserId());
        rechargeOrder.setOperatorName(sysUser.getUserName());
        rechargeOrder.setCommunityId(community.getId());
        rechargeOrder.setCommunityName(community.getCommunityName());
        rechargeOrder.setDeviceId(device.getId());
        rechargeOrder.setDeviceNum(device.getDeviceNum());
        rechargeOrder.setState(0);
        rechargeOrder.setOrderState(0);
        rechargeOrder.setOrderType(device.getBillingType());
        rechargeOrder.setHoleNum(socketNo+"");
        rechargeOrder.setOrderNum(OrderNumUtil.getOrderNum());
        rechargeOrder.setPreinstallMoney(money);

        rechargeOrder.setCreateTime(new Date());
        rechargeOrderMapper.insertSelective(rechargeOrder);

        //下发充电
        JSONObject jsonObject = null;
        try {
            jsonObject = ClientUtils.doGetMethod("http://localhost:8610/start/charge?orderNo=" + rechargeOrder.getOrderNum()
                    + "&orderTime=" + chargeTime
                    + "&socketNo=" + socketNo
                    + "&deviceNum=" + deviceNum
                    + "&userBalance=" + money);

        } catch (IOException e) {
            e.printStackTrace();
        }
        if (StringUtils.isNull(jsonObject) || !"200".equals(jsonObject.getString("code"))) {
            throw new ServiceException("充电失败！请稍后再试。");
        }

        return rechargeOrder.getId();
    }

    private void checkStatus(String deviceNum) {
        log.info("握手开始");
        int msgId = Integer.parseInt(OrderNumUtil.getRandom());
        log.info(msgId+"");
        //加锁asd
        mqttLockUtil.lock(msgId + "");
        try {
            JSONObject jsonObject = ClientUtils.doGetMethod("http://localhost:8610/check?deviceNum=" + deviceNum + "&msgId=" + msgId);
            log.info(jsonObject.toJSONString());
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException("设备无响应,请稍后再试!");
        }
        if (!mqttLockUtil.checkLock(msgId + "", 10)) {
            throw new ServiceException("设备无响应!");
        }
    }
}
